package net.easyjava.third.letv.api;

import net.easyjava.third.letv.https.EasyX509HostnameVerifier;
import net.easyjava.third.letv.https.EasyX509TrustManager;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.ByteArrayBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.*;
import java.util.Map.Entry;

/**
 * @author liufengyu
 * @date 2014年11月11日
 */
class RestTemplate {
    private static final Logger log = LoggerFactory.getLogger(RestTemplate.class);

    private HttpClient client;

    public RestTemplate() {
        try {
            TrustManager easyTrustManager = new EasyX509TrustManager();
            X509HostnameVerifier easyHostnameVerifier = new EasyX509HostnameVerifier();

            SSLContext sslcontext;
            sslcontext = SSLContext.getInstance("TLS");
            sslcontext.init(null, new TrustManager[]{easyTrustManager}, null);

            SSLSocketFactory sf = new SSLSocketFactory(sslcontext, easyHostnameVerifier);
            SchemeRegistry schemeRegistry = new SchemeRegistry();
            schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
            schemeRegistry.register(new Scheme("https", 443, sf));

            PoolingClientConnectionManager cm = new PoolingClientConnectionManager(schemeRegistry);
            cm.setMaxTotal(2000);
            cm.setDefaultMaxPerRoute(1000);

            this.client = new DefaultHttpClient(cm);
        } catch (Exception e) {
        }
    }

    public RestTemplate(PoolingClientConnectionManager cm) {
        this.client = new DefaultHttpClient(cm);
    }

    //*********************************************
    public HttpResponse postForObject(String url, Map<String, String> params, Map<String, String> headers)
            throws IOException {
        HttpPost post = new HttpPost(url);
        List<BasicNameValuePair> data = new ArrayList<BasicNameValuePair>();
        StringBuilder sb = new StringBuilder();
        if (params != null && params.size() > 0) {
            for (Entry<String, String> entry : params.entrySet()) {
                data.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
                sb.append(entry.getKey()).append("=").append(entry.getValue()).append(";");
            }
        }
        if (headers != null && headers.size() > 0) {
            for (Entry<String, String> entry : headers.entrySet()) {
                post.addHeader(entry.getKey(), entry.getValue());
            }
        }
        long start = System.currentTimeMillis();
        post.setEntity(new UrlEncodedFormEntity(data, "UTF-8"));
        HttpResponse response = client.execute(post);
        long cost = System.currentTimeMillis() - start;
        log.debug("LetvApi Post cost={}ms, statusCode={}, url={}，params={}", cost, response.getStatusLine()
                .getStatusCode(), url, sb);
        return response;
    }

    public HttpResponse postMultipartForObject(String url, Map<String, String> params, Map<String, byte[]> multipart) {
        MultipartEntity requestEntity = new MultipartEntity();
        if (params != null && params.size() > 0) {
            for (Entry<String, String> entry : params.entrySet()) {
                try {
                    requestEntity.addPart(entry.getKey(), new StringBody(entry.getValue(), Charset.forName("UTF-8")));
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }
        if (multipart != null && multipart.size() > 0) {
            for (Entry<String, byte[]> entry : multipart.entrySet()) {
                ByteArrayBody bab = new ByteArrayBody(entry.getValue(), "multipart/form-data", entry.getKey());
                requestEntity.addPart(entry.getKey(), bab);
            }
        }
        HttpPost post = new HttpPost(url);
        post.setEntity(requestEntity);
        try {
            return client.execute(post);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    public HttpResponse getForObject(String url, Map<String, String> params) throws IOException {
        return this.getForObject(url, params, null);
    }

    public HttpResponse getForObject(String url, Map<String, String> params, Map<String, String> headers)
            throws IOException {
        StringBuilder tmp = new StringBuilder(url);

        if (params != null && params.size() > 0) {
            tmp.append("?");
            Set<Entry<String, String>> entries = params.entrySet();
            for (Iterator<Entry<String, String>> iterator = entries.iterator(); iterator.hasNext(); ) {
                Entry<String, String> entry = iterator.next();
                tmp.append(entry.getKey());
                tmp.append("=");
                try {
                    tmp.append(java.net.URLEncoder.encode(entry.getValue(), "UTF-8"));
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
                if (iterator.hasNext()) {
                    tmp.append("&");
                }
            }
        }

        url = tmp.toString();
        HttpGet get = new HttpGet(url);
        if (headers != null && headers.size() > 0) {
            for (Entry<String, String> entry : headers.entrySet()) {
                get.addHeader(entry.getKey(), entry.getValue());
            }
        }
        long start = System.currentTimeMillis();
        HttpResponse response = client.execute(get);
        long cost = System.currentTimeMillis() - start;
        log.debug("LetvApi Get cost={}ms, statusCode={}, url={}", cost, response.getStatusLine().getStatusCode(), url);
        return response;
    }

    public HttpResponse deleteForObject(String url, Map<String, String> params, Map<String, String> headers)
            throws IOException {
        StringBuilder tmp = new StringBuilder(url);
        if (params != null && params.size() > 0) {
            tmp.append("?");
            Set<Entry<String, String>> entries = params.entrySet();
            for (Iterator<Entry<String, String>> iterator = entries.iterator(); iterator.hasNext(); ) {
                Entry<String, String> entry = iterator.next();
                tmp.append(entry.getKey());
                tmp.append("=");
                try {
                    tmp.append(java.net.URLEncoder.encode(entry.getValue(), "UTF-8"));
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
                if (iterator.hasNext()) {
                    tmp.append("&");
                }
            }
        }

        HttpDelete delete = new HttpDelete(tmp.toString());
        if (headers != null && headers.size() > 0) {
            for (Entry<String, String> entry : headers.entrySet()) {
                delete.addHeader(entry.getKey(), entry.getValue());
            }
        }

        long start = System.currentTimeMillis();
        HttpResponse response = client.execute(delete);
        long cost = System.currentTimeMillis() - start;
        log.debug("LetvApi Delete cost={}ms, statusCode={}, url={}", cost, response.getStatusLine().getStatusCode(),
                url);
        return response;
    }

//	public HttpResponse putForObject(String url, Map<String, String> params, Map<String, String> headers)
//	        throws IOException {
//		// 通过ENTITY提交参数
//		HttpPut put = new HttpPut(url);
//		List<BasicNameValuePair> data = new ArrayList<BasicNameValuePair>();
//		StringBuilder sb = new StringBuilder();
//		if (params != null && params.size() > 0) {
//			Set<Entry<String, String>> entries = params.entrySet();
//			for (Entry<String, String> entry : entries) {
//				data.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
//				sb.append(entry.getKey()).append("=").append(entry.getValue()).append(";");
//			}
//			put.setEntity(new UrlEncodedFormEntity(data, "UTF-8"));
//		}
//
//		if (headers != null && headers.size() > 0) {
//			for (Entry<String, String> entry : headers.entrySet()) {
//				put.addHeader(entry.getKey(), entry.getValue());
//			}
//		}
//
//		// 通过URL提交参数
////        StringBuilder tmp = new StringBuilder(url);
////        tmp.append("?");
////        for (Iterator<Entry<String, String>> iterator = map.entrySet().iterator(); iterator.hasNext();) {
////            Entry<String, String> entry = iterator.next();
////            tmp.append(entry.getKey());
////            tmp.append("=");
////            tmp.append(java.net.URLEncoder.encode(entry.getValue(), "UTF-8"));
////            if (iterator.hasNext()) {
////                tmp.append("&");
////            }
////        }
////        HttpPut put = new HttpPut(tmp.toString());
//		long start = System.currentTimeMillis();
//		HttpResponse response = client.execute(put);
//		long cost = System.currentTimeMillis() - start;
//		log.debug("LetvApi Put cost={}ms, statusCode={}, url={}，params={}", cost, response.getStatusLine()
//		        .getStatusCode(), url, sb);
//		return response;
//	}
}
